﻿using Core.SimpleTemp.Common;
using Core.Toolkit.Core.Entitys;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;

namespace Core.Toolkit.Core.Repositories.Internal
{
    /// <summary>
    /// 仓储基类
    /// </summary>
    /// <typeparam name="TEntity">实体类型</typeparam>
    /// <typeparam name="TPrimaryKey">主键类型</typeparam>
    public partial class BaseDBRepository<TDbContext, TEntity, TPrimaryKey> where TEntity : Entity<TPrimaryKey> where TDbContext : DbContext
    {
        //定义数据访问上下文对象
        public readonly TDbContext _dbContext;
        public readonly IEnumerable<string> _properties;
        /// <summary>
        /// 通过构造函数注入得到数据上下文对象实例
        /// </summary>
        /// <param name="dbContext"></param>
        public BaseDBRepository(TDbContext dbContext)
        {
            _dbContext = dbContext;
        }

        public DbSet<TEntity> Set => _dbContext.Set<TEntity>();

        public virtual IQueryable<TEntity> QueryBase()
        {
            IQueryable<TEntity> ret = Set;
            #region 逻辑删除过滤
            Expression<Func<TEntity, bool>> where = ExpressionExtension.True<TEntity>();
            where = where.And(e => e.IsDeleted == false);

            #endregion
            ret = ret.Where(where);
            return ret;
        }


        /// <summary>
        /// 根据主键获取实
        /// </summary>
        /// <param name="id">实体主键</param>
        /// <param name="baseQuery">baseQuery</param>
        /// <returns></returns>
        public virtual Task<TEntity> GetAsync(TPrimaryKey id, IQueryable<TEntity> baseQuery = null)
        {
            IQueryable<TEntity> ret = QueryBase();
            if (baseQuery != null)
                ret = baseQuery;
            return ret.FirstOrDefaultAsync(CreateEqualityExpressionForId(id));
        }



        /// <summary>
        /// 新增实体
        /// </summary>
        /// <param name="entity">实体</param>
        /// <param name="autoSave">是否立即执行保存</param>
        /// <returns></returns>
        public virtual async Task<TEntity> InsertAsync(TEntity entity, bool autoSave = true)
        {
            var addEntity = await _dbContext.Set<TEntity>().AddAsync(entity);
            if (autoSave)
                await SaveAsync();
            return addEntity.Entity;
        }

        /// <summary>
        /// 更新实体(待优化)
        /// </summary>
        /// <param name="entity">实体</param>
        /// <param name="noUpdateProperties">不更新哪些属性</param>
        /// <param name="autoSave">是否立即执行保存</param>
        public virtual async Task<TEntity> UpdateAsync(TEntity entity, bool autoSave = true, List<string> noUpdateProperties = null)
        {
            var obj = await GetAsync(entity.Id);
            EntityToEntity(entity, obj, noUpdateProperties);
            return await UpdateAsync(obj, autoSave);
        }


        /// <summary>
        /// 更新实体（需要先从EF中查询出来再做更新)
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="autoSave"></param>
        /// <returns></returns>
        public virtual async Task<TEntity> UpdateAsync(TEntity entity, bool autoSave = true)
        {
            if (autoSave)
                await SaveAsync();
            return entity;
        }

        /// <summary>
        /// 删除实体 根据实体进行删除
        /// </summary>
        /// <param name="entity">要删除的实体</param>
        /// <param name="autoSave">是否立即执行保存</param>
        public virtual async Task DeleteAsync(TEntity entity, bool autoSave = true)
        {
            _dbContext.Set<TEntity>().Remove(entity);
            if (autoSave)
                await SaveAsync();
        }

        /// <summary>
        /// 删除实体
        /// </summary>
        /// <param name="id">实体主键</param>
        /// <param name="autoSave">是否立即执行保存</param>
        public virtual async Task DeleteAsync(TPrimaryKey id, bool autoSave = true)
        {
            _dbContext.Set<TEntity>().Remove(await GetAsync(id));
            if (autoSave)
                await SaveAsync();
        }

        /// <summary>
        /// 根据条件删除实体
        /// </summary>
        /// <param name="where">lambda表达式</param>
        /// <param name="autoSave">是否自动保存</param>
        public virtual async Task DeleteAsync(Expression<Func<TEntity, bool>> where, bool autoSave = true)
        {
            _dbContext.Set<TEntity>().Where(where).ToList().ForEach(it => _dbContext.Set<TEntity>().Remove(it));
            if (autoSave)
                await SaveAsync();
        }

        /// <summary>
        /// 事务性保存
        /// </summary>
        public virtual Task<int> SaveAsync()
        {
            return _dbContext.SaveChangesAsync();
        }


    }

    /// <summary>
    /// 主键为Guid 的指定仓储
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    public abstract class BaseDBRepository<TDbContext, TEntity> : BaseDBRepository<TDbContext, TEntity, Guid> where TEntity : Entity, new() where TDbContext : DbContext
    {
        public BaseDBRepository(TDbContext dbContext) : base(dbContext)
        {
        }
    }




}
